package com.dkts.oil.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * ApplicationContext 请求工具类
 *
 * @author Wulijun
 * @date 2021/10/19 15:42
 */
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    final static String unknown = "unknown";

    /**
     * 获取本地ip地址
     *
     * @param request
     * @return String
     * @author wulijun
     * @date 2021/10/19 15:55
     */
    public static String getRemoteIpAdrress(HttpServletRequest request) {
        String ip = null;
        // X-Forwarded-For：Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");

        if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {
            // Proxy-Client-IP：apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {
            // WL-Proxy-Client-IP：weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {
            // HTTP_CLIENT_IP：有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {
            // X-Real-IP：nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }
        // 有些网络通过多层代理，那么获取到的ip就会有多个，一般都是通过逗号（,）分割，
        // 并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }

        // 还是不能获取到，最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }

    @Override
    @SuppressWarnings("null")
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        applicationContext = context;
    }

    public static ApplicationContext getContext() {
        return applicationContext;
    }

    @SuppressWarnings("null")
    public static HttpServletRequest getHttpServletRequest() {
        return (HttpServletRequest) ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
    }

    @SuppressWarnings("null")
    public static HttpServletResponse getHttpServletResponse() {
        return (HttpServletResponse) ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getResponse();
    }

    /**
     * 获取用户处理Bean, 没有则动态注入（单例bean）
     * 
     * @param beanName        bean名称
     * @param singletonObject 单例bean实例
     * @return 注入实例
     */
    public static Object getBean(String beanName) {
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;

        Object resObject = configurableApplicationContext.getBean(beanName);
        if (resObject.equals(null)) {
            // 获取BeanFactory
            DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext
                    .getAutowireCapableBeanFactory();

            // 动态注册bean.
            defaultListableBeanFactory.registerSingleton(beanName, resObject);
        }
        return resObject;
    }

    // Request Attribute 操作
    public static void setReqAttribute(String key, Object value) {
        getHttpServletRequest().setAttribute(key, value);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getReqAttribute(String key) {
        Object val = getHttpServletRequest().getAttribute(key);
        if (val == null) return null;
        return (T) getHttpServletRequest().getAttribute(key);
    }
}
